package cc.rengu.igas.opms.core.service.trans.apppay;

import cc.rengu.chargecalc.mchntfee.CalcMchntFee;
import cc.rengu.chargecalc.mchntfee.model.CalcMchntFeeResultBean;
import cc.rengu.chargecalc.mchntfee.model.CalcMchntFeeBean;
import cc.rengu.igas.momp.facade.base.Header;
import cc.rengu.igas.momp.facade.bean.PaymentOrderCouponInfoBean;
import cc.rengu.igas.momp.facade.bean.PaymentOrderDetailBean;
import cc.rengu.igas.momp.facade.request.ComboPaymentRequest;
import cc.rengu.igas.momp.facade.request.ComboPaymentReversalRequest;
import cc.rengu.igas.momp.facade.response.ComboPaymentResponse;
import cc.rengu.igas.momp.facade.result.Result;
import cc.rengu.igas.opms.common.constant.OpmsServiceConstant;
import cc.rengu.igas.opms.common.constant.OpmsTreeNodeConstant;
import cc.rengu.igas.opms.common.constant.OpmsParamConstant;
import cc.rengu.igas.opms.common.entity.TransLimitBean;
import cc.rengu.igas.opms.common.enums.ChannelTypeEnum;
import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.opms.common.util.OpmsUpacSecurityUtil;
import cc.rengu.igas.opms.core.service.base.PayService;
import cc.rengu.igas.opms.facade.request.UnionPayRequest;
import cc.rengu.igas.opms.facade.response.UnionPayResponse;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.constant.ShareServiceConstant;
import cc.rengu.igas.share.common.constant.ShareTreeNodeConstant;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.jradp.asynnotify.AsynNotify;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.CertInfoMapper;
import cc.rengu.oltp.service.common.dao.DstChannelCfgMapper;
import cc.rengu.oltp.service.common.dao.MchntOrderDetailMapper;
import cc.rengu.oltp.service.common.dao.SecPlanInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.CertInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.DstChannelCfgMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderDetailMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SecPlanInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.TransCustomImpl;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.io.FileUtils;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 云闪付服务类
 *
 * @author keyi
 * @modify by wangcheng
 * @date 2020/4/21.
 */
public class UnionPayService extends PayService implements TransCustomImpl {

    /**
     * 是否带优惠劵的交易
     */
    private boolean isCouponTrans;

    @Override
    protected Object bizBeforeCust() throws Exception {
        UnionPayRequest unionPayRequest = new UnionPayRequest();
        ConvertUtil.convertOutput(unionPayRequest);
        return unionPayRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        UnionPayRequest unionPayRequest = (UnionPayRequest) request;
        String instId = unionPayRequest.getHeader().getInstId();
        String session = unionPayRequest.getHeader().getSession();
        String txnNum = unionPayRequest.getHeader().getTxnNum();
        String userOrderId = unionPayRequest.getUserOrderId();
        String transAmt = unionPayRequest.getOrderAmt();
        String userId = unionPayRequest.getUserId();

        List<ChannelCallCfg> mompTxnNumList = txnInfo.getChannelCallCfgList().stream().filter(channelCallCfg -> ChannelEnum.MOMP.getChannelType().equals(channelCallCfg.getCallChannelId())).collect(Collectors.toList());

        MchntService mchntService = new MchntServiceImpl();
        //step1.获取授信标识
        isCouponTrans = null != unionPayRequest.getCouponInfo() && !StringUtil.isEmptyOrNull(unionPayRequest.getCouponInfo().getDiscountId());

        //step3.校验订单信息
        OrderService orderService = new OrderServiceImpl();
        OrderInfo orderInfo = orderService.selectOrderInfoByUserOrderId(instId, userOrderId);
        if (null == orderInfo) {
            rglog.error("订单信息不存在!");
            throw new BizException(RespCodeEnum.ORDER_NOEXIT.getRespCode(), RespCodeEnum.ORDER_NOEXIT.getRespDesc());
        }
        UserOrderInfo userOrderInfo = orderInfo.getUserOrderInfo();
        /*登记支付备注*/
        userOrderInfo.setOrderDesc(unionPayRequest.getOrderDesc());
        List<MchntOrderInfo> mchntOrderInfoList = orderInfo.getMchntOrderInfoList();

        //获取全渠道后台通知地址
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParamInfo = sysParamService.getSysParamInfo(instId, OpmsParamConstant.UPAC_CONF_NODE, OpmsParamConstant.UPAC_BANK_URL);
        if (null == sysParamInfo || AppParamConstant.NO.equals(sysParamInfo.getParamStatus())) {
            rglog.info("机构全渠道后台通知地址未配置,instId:<{}>", instId);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }

        String prodType = "";
        String upacMchntNo = "";
        List<TransLimitBean> transLimitBeanList = new ArrayList<>();
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            //step4.检查商户是否支持银联全渠道 全渠道合并订单支付要求各子商户的全渠道商户号相同
            MchntInfo mchntInfo = mchntService.getMchntInfo(instId, mchntOrderInfo.getMchntNo());
            if (null == mchntInfo || StringUtil.isEmptyOrNull(mchntInfo.getCupsMchntNo()) || mchntInfo.getCupsMchntNo().isEmpty()) {
                rglog.error("银联商户信息不存在或该商户无银联全渠道商户号");
                throw new BizException(RespCodeEnum.MCHNT_NO_PERMISSION.getRespCode(), RespCodeEnum.MCHNT_NO_PERMISSION.getRespDesc());
            } else {
                Map<String, Object> mchntMap = JSONObject.parseObject(mchntInfo.getCupsChannelMchntNo());
                for (Map.Entry entry : mchntMap.entrySet()) {
                    if (((String) entry.getKey()).startsWith("GW")) {
                        //校验商户号
                        if (!StringUtil.isEmptyOrNull(upacMchntNo) && !upacMchntNo.equals(entry.getValue())) {
                            rglog.info("合并订单支付时各子商户的全渠道商户号必须相同");
                            throw new BizException(RespCodeEnum.UPAC_MCHNT_DIFF.getRespCode(), RespCodeEnum.UPAC_MCHNT_DIFF.getRespDesc());
                        }
                        prodType = (String) entry.getKey();
                        upacMchntNo = (String) entry.getValue();
                        break;
                    }
                }
                if (StringUtil.isEmptyOrNull(upacMchntNo) || StringUtil.isEmptyOrNull(prodType)) {
                    rglog.error("商户未开通银联业务，不支持银联网关支付");
                    throw new BizException(RespCodeEnum.MCHNT_NO_PERMISSION.getRespCode(), RespCodeEnum.MCHNT_NO_PERMISSION.getRespDesc());
                }
            }

            //step5.商户限额检查
            int limitFlag = mchntService.checkMchntTransLimit(instId, mchntOrderInfo.getRealSettleAmt(), LimitAcctTypeEnum.ALL, mchntOrderInfo.getMchntNo(), null, txnNum);
            if (limitFlag == 2 || limitFlag == 3) {
                rglog.error("商户金额超限");
                throw new BizException(RespCodeEnum.MCHNT_AMT_OVER.getRespCode(), RespCodeEnum.MCHNT_AMT_OVER.getRespDesc());
            } else if (limitFlag == 1) {
                /*不支持信用卡*/
                xmlTreeUtil.setXmlTreeStringValue("disablePayChannels", "pcredit");
            }

            //更新商户订单，支付前不计算商户手续费
            mchntOrderInfo.setTxnDate(userOrderInfo.getTxnDate());
            mchntOrderInfo.setTxnTime(userOrderInfo.getTxnTime());
            mchntOrderInfo.setBizType(unionPayRequest.getHeader().getBizType());
            mchntOrderInfo.setTxnNum(unionPayRequest.getHeader().getTxnNum());
            mchntOrderInfo.setSysSeqNum(sysSeqNum);
            mchntOrderInfo.setMchntDiscountFee("0.00");
            mchntOrderInfo.setRealMchntFee("0.00");
            mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
            mchntOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
            mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            String realSettleFlag = mchntService.getRealSettleFlag(mchntInfo.getMchntNo(), txnInfo.getSrcTxnAuthCfg().getBizProdCode(), mchntOrderInfo.getBizSceneType(), mchntOrderInfo.getRealSettleAmt());
            mchntOrderInfo.setRealSettleFlag(realSettleFlag);
            mchntOrderInfo.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
        }

        /*合并订单支付，不能合并特殊费率跟非特殊费率，不能合并d0清算跟非d0清算*/
        if (mchntOrderInfoList.size() > 1) {
            List<MchntOrderInfo> mchntOrderInfoSpFeeList = mchntOrderInfoList.stream().filter(item -> "0".equals(item.getFeeInputMode())).collect(Collectors.toList());
            if (!mchntOrderInfoSpFeeList.isEmpty() && mchntOrderInfoSpFeeList.size() != mchntOrderInfoList.size()) {
                rglog.error("合并订单中存在特殊费率跟非特殊费率的订单，拒绝交易");
                throw new BizException(RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespCode(), RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespDesc());
            }
            List<MchntOrderInfo> mchntOrderInfoD0List = mchntOrderInfoList.stream().filter(item -> AppParamConstant.YES.equals(item.getRealSettleFlag())).collect(Collectors.toList());
            if (!mchntOrderInfoD0List.isEmpty() && mchntOrderInfoD0List.size() != mchntOrderInfoList.size()) {
                rglog.error("合并订单中存在d0清算跟非d0清算的订单，拒绝交易");
                throw new BizException(RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespCode(), RespCodeEnum.ORDER_NOT_ALLOW_PAY.getRespDesc());
            }
        }

        /*更新订单明细表*/
        List<MchntOrderDetail> mchntOrderDetailList = new ArrayList<>();
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            MchntOrderDetailMapper mchntOrderDetailMapper = new MchntOrderDetailMapperImpl();
            List<MchntOrderDetail> oneMchntOrderDetailList = mchntOrderDetailMapper.selectMchntOrderDetailByMchntOrderId(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo(), mchntOrderInfo.getMchntOrderId());
            if (!CollectionUtils.isEmpty(oneMchntOrderDetailList)) {
                for (MchntOrderDetail mchntOrderDetail : oneMchntOrderDetailList) {
                    mchntOrderDetail.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
                }
                mchntOrderDetailList.addAll(oneMchntOrderDetailList);
            }
        }
        if (!CollectionUtils.isEmpty(mchntOrderDetailList)) {
            orderService.updateOrderInfo(null, null, mchntOrderDetailList, null);
        }
        //更新用户订单表/商户订单表
        if (!updateOrderInfo(userOrderInfo, mchntOrderInfoList, null)) {
            rglog.error("更新订单信息失败");
            throw new BizException(RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespCode(),
                    RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
        }

        //交易限额信息存入缓存
        xmlTreeUtil.setXmlTreeObjectValue(OpmsTreeNodeConstant.TRANS_LIMIT_INFO_LIST, transLimitBeanList);

        //step7.调用营销进行试算并解析应答结果
        PayOrderInfo mompPayOrder = registMompOrderInfo(userOrderInfo, mompTxnNumList.get(0));
        if (null == mompPayOrder) {
            updateUserAndMchntOrderInf(userOrderInfo, mchntOrderInfoList, null, orderService);
            throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
        }
        mompPayOrder.setRealPayAmt(unionPayRequest.getOrderAmt());
        xmlTreeUtil.setXmlTreeObjectValue(OpmsTreeNodeConstant.PAY_ORDER_INFO, mompPayOrder);
        Result<ComboPaymentResponse> mompResult = callMompPayServcie(unionPayRequest, mchntOrderInfoList, mompTxnNumList.get(OpmsParamConstant.INT_ZERO), isCouponTrans);
        analysisMompResult(userOrderInfo, mchntOrderInfoList, mompPayOrder, mompResult, orderService, mompTxnNumList.get(0), isCouponTrans, unionPayRequest);

        //登记支付订单表
        PayOrderInfo payOrderInfo = registPayOrderInfo(userOrderInfo, prodType, upacMchntNo);
        if (null == payOrderInfo) {
            updateUserAndMchntOrderInf(userOrderInfo, mchntOrderInfoList, null, orderService);
            mompRevsal(mompTxnNumList.get(1));
            throw new BizException(RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespCode(), RespCodeEnum.INSERT_PAY_ORDER_ERROR.getRespDesc());
        }

        //step8. 异步调起通道交易状态查询任务，获取交易状态
        GlobalTransUtil.setCacheValue(TransCacheConstant.USER_ORDER_INFO, userOrderInfo);
        GlobalTransUtil.setCacheValue(TransCacheConstant.MCHNT_ORDER_INFO_LIST, mchntOrderInfoList);
        AsynNotify asynNotify = new AsynNotify();
        int iReturnCode = asynNotify.transactionNotice(ShareServiceConstant.ASYN_PAYORDERSTATUS_QUERY_SERVICE, 5, AsynNotify.GAP_SAME, 60 * 1000);
        if (iReturnCode != 0) {
            rglog.error("异步调起云闪付交易状态查询失败");
        }

        //构建响应内容
        String orderId = payOrderInfo.getChannelReconKey();
        String orderTime = payOrderInfo.getTxnDate() + payOrderInfo.getTxnTime();
        return getResponse(instId, prodType, upacMchntNo, orderId, orderTime, userOrderInfo.getRealPayAmt(), sysParamInfo.getParamValue());
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        UnionPayResponse unionPayResponseest = (UnionPayResponse) bizResponse.getResult();
        ConvertUtil.convertInput(unionPayResponseest);
    }

    /**
     * 营销试算接口调用
     *
     * @param unionPayRequest    请求实体
     * @param mchntOrderInfoList 商户订单集合
     * @param channelCallCfg     通道服务调用配置
     * @param isCouponTrans      是否使用卡劵
     * @return DUBBO响应
     * @throws Exception 异常
     */
    private Result<ComboPaymentResponse> callMompPayServcie(UnionPayRequest unionPayRequest, List<MchntOrderInfo> mchntOrderInfoList, ChannelCallCfg channelCallCfg, boolean isCouponTrans) throws Exception {

        //获取营销产品列表
        String paramKey = txnInfo.getSrcTxnAuthCfg().getTxnNum() + txnInfo.getSrcTxnAuthCfg().getBizType();
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParamInfo = sysParamService.getSysParamInfo(unionPayRequest.getHeader().getInstId(), OpmsParamConstant.MOMP_PROD_CODE, paramKey);
        if (null == sysParamInfo) {
            rglog.warn("营销产品编码未配置,instId:<{}>", unionPayRequest.getHeader().getInstId());
            return null;
        }

        //合并支付请求
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        Header header = new Header();
        header.setInstId(unionPayRequest.getHeader().getInstId());
        header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
        header.setSrcSysId(AppParamConstant.SYS_ID);
        header.setBizType(AppParamConstant.DEFAULT_BIZ_TYPE);
        header.setTxnNum(channelCallCfg.getCallChannelTxn());
        header.setVersion("1.0.0");
        header.setTraceNo(sysSeqNum + channelCallCfg.getCallIndex());
        header.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        header.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        //营销合并支付请求体
        ComboPaymentRequest comboPaymentRequest = new ComboPaymentRequest();
        ConvertUtil.convertOutput(comboPaymentRequest);
        comboPaymentRequest.setHeader(header);
        comboPaymentRequest.setBizProdCode(sysParamInfo.getParamValue());
        comboPaymentRequest.setMchntOrderId(unionPayRequest.getUserOrderId());
        comboPaymentRequest.setTransAmt(unionPayRequest.getOrderAmt());
        comboPaymentRequest.setUserId(unionPayRequest.getUserId());
        List<PaymentOrderDetailBean> orderDetailList = new ArrayList<>();
        convertOrderDetail(orderDetailList, mchntOrderInfoList);
        comboPaymentRequest.setOrderDetailList(orderDetailList);
        if (isCouponTrans) {
            List<PaymentOrderCouponInfoBean> couponInfoList = new ArrayList<>();
            PaymentOrderCouponInfoBean paymentOrderCouponInfoBean = new PaymentOrderCouponInfoBean();
            paymentOrderCouponInfoBean.setCouponNo(unionPayRequest.getCouponInfo().getDiscountId());
            comboPaymentRequest.setCouponInfoList(couponInfoList);
        }
        xmlTreeUtil.setXmlTreeObjectValue("comboPaymentRequest", comboPaymentRequest);
        DubboService dubboService = new DubboServiceImpl();
        try {
            return (Result<ComboPaymentResponse>) dubboService.callDubboService(OpmsParamConstant.DUBBO_MOMP_PAYMENT_SERVICE, "comboPayment", comboPaymentRequest);
        } catch (Exception e) {
            rglog.error("调用营销试算接口异常:<{}>", e);
            return null;
        }
    }

    /**
     * 订单转换
     *
     * @param orderDetailList    请求营销订单明细
     * @param mchntOrderInfoList 商户订单集合
     */
    private void convertOrderDetail(List<PaymentOrderDetailBean> orderDetailList, List<MchntOrderInfo> mchntOrderInfoList) {
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            PaymentOrderDetailBean paymentOrderDetailBean = new PaymentOrderDetailBean();
            paymentOrderDetailBean.setMchntNo(mchntOrderInfo.getMchntNo());
            if (mchntOrderInfo.getOrderDiscountAmt() != null && !mchntOrderInfo.getOrderDiscountAmt().isEmpty()) {
                paymentOrderDetailBean.setOrderAmt(AmountUtil.subtraction(mchntOrderInfo.getOrderAmt(), mchntOrderInfo.getOrderDiscountAmt()));
            } else {
                paymentOrderDetailBean.setOrderAmt(mchntOrderInfo.getOrderAmt());
            }
            paymentOrderDetailBean.setMchntFeeReceivableRate(mchntOrderInfo.getFeeRate());
            paymentOrderDetailBean.setMchntSettleAmt(mchntOrderInfo.getRealSettleAmt());
            paymentOrderDetailBean.setMchntFeeReceivable(mchntOrderInfo.getMchntFee());
            paymentOrderDetailBean.setFeeInputMode("0");
            paymentOrderDetailBean.setFeeType("");
            paymentOrderDetailBean.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
            orderDetailList.add(paymentOrderDetailBean);
        }
    }

    /**
     * 解析营销合并支付调用结果
     *
     * @param userOrderInfo      用户订单表
     * @param mchntOrderInfoList 商户订单表
     * @param mompPayOrderInfo   营销支付订单表
     * @param mompResult         营销合并支付调用结果
     * @param orderService       订单操作组件
     * @param channelCallCfg     通道服务调用配置
     * @param isCouponTrans      是否使用优惠劵
     * @throws Exception 异常
     */
    private void analysisMompResult(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo mompPayOrderInfo, Result<ComboPaymentResponse> mompResult,
                                    OrderService orderService, ChannelCallCfg channelCallCfg, boolean isCouponTrans, UnionPayRequest unionPayRequest) throws Exception {
        String discountFlag = AppParamConstant.NO;
        String feeDiscountFlag = AppParamConstant.NO;
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);

        if (null == mompResult || !mompResult.isSuccess()) {
            if (isCouponTrans) {
                rglog.warn("使用卡劵交易调用营销失败,整个交易失败");
                updateUserAndMchntOrderInf(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo, orderService);
                throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            } else {
                mompPayOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                mompPayOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                mompPayOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo)) {
                    rglog.warn("更新用户订单/商户订单信息失败");
                }
                rglog.debug("交易调用营销失败但未使用卡劵可继续进行交易");
            }
        }

        ComboPaymentResponse mompResponse = mompResult.getResult();
        //营销调用超时，向营销系统异步发起冲正
        if (OpmsParamConstant.DUBBO_OVERTIME.equals(mompResponse.getRespCode())) {
            rglog.info("营销试算DUBBO接口-调用超时，发起冲正");
            //更新用户订单表/商户订单表状态为失败
            updateUserAndMchntOrderInf(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo, orderService);
            mompRevsal(channelCallCfg);
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        } else if (!OpmsParamConstant.DUBBO_SUCCESS.equals(mompResponse.getRespCode())) {
            if (isCouponTrans) {
                rglog.error("使用卡劵交易调用营销失败,整个交易失败");
                updateUserAndMchntOrderInf(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo, orderService);
                throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            } else {
                mompPayOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                mompPayOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                mompPayOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo)) {
                    rglog.warn("更新用户订单/商户订单信息失败");
                }
                rglog.debug("交易调用营销失败但未使用卡劵可继续进行交易");
            }
        } else {

            //判断是否使用营销 参与营销，不实时入账
            if (AmountUtil.compare(mompResponse.getTransAmt(), mompResponse.getTxnAmt()) != 0) {
                discountFlag = AppParamConstant.YES;
            }

            //更新用户订单实际支付金额和优惠金额
            userOrderInfo.setRealPayAmt(mompResponse.getTxnAmt());
            userOrderInfo.setRealDiscountAmt(AmountUtil.subtraction(userOrderInfo.getOrderAmt(), mompResponse.getTxnAmt()));
            if (null != unionPayRequest.getCouponInfo() && null != unionPayRequest.getCouponInfo().getDiscountId()) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put(unionPayRequest.getCouponInfo().getDiscountId(), unionPayRequest.getCouponInfo().getDiscountAmt());
                userOrderInfo.setDiscountInfo(jsonObject.toJSONString());
            }

            List<PaymentOrderDetailBean> orderDetailBeanList = mompResponse.getOrderDetailList();
            if (orderDetailBeanList == null || orderDetailBeanList.isEmpty()) {
                rglog.warn("营销返回数据有误");
                updateUserAndMchntOrderInf(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo, orderService);
                mompRevsal(channelCallCfg);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }

            //计算商户的优惠信息
            /*通道优惠金额累加*/
            String channelDiscountAmt = "0.00";
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {

                List<PaymentOrderDetailBean> paymentOrderDetailBeanList = orderDetailBeanList.stream().filter(item -> item.getMchntNo().equals(mchntOrderInfo.getMchntNo())).collect(Collectors.toList());
                if (paymentOrderDetailBeanList.isEmpty()) {
                    rglog.warn("当前商户无营销优惠信息，在订单明细列表中无当前商户数据。mchntNo:<{}>", mchntOrderInfo.getMchntNo());
                    updateUserAndMchntOrderInf(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo, orderService);
                    xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);
                    mompRevsal(channelCallCfg);
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                }

                /*用户优惠金额(免充值优惠金额)*/
                String customerAmt = "0.00";

                /*
                 * 判断是否是免充值的商户优惠类型
                 * 若不是则使用营销返回的数据
                 * 商户清算本金金额=原商户清算本金金额
                 * 商户结算金额=商户清算本金金额-实收商户手续费
                 * 若是则需要重新获取商户清算本金金额并重新计算商户手续费
                 * 商户清算本金金额=原商户清算本金金额-免充值金额
                 * 商户结算金额=商户清算本金金额-商户应收手续费(调用批量结算结果)+手续费优惠金额(营销返回)
                 */
                String noRechargeAmt = "0.00";
                if ("0".equals(paymentOrderDetailBeanList.get(0).getMoneyOffSettlementMethod())) {
                    /*免充值需要减去商户满减补贴金额*/
                    noRechargeAmt = AmountUtil.addition(noRechargeAmt, paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyMchnt());
                    /*用户优惠金额累计*/
                    customerAmt = AmountUtil.addition(customerAmt, paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyMchnt());
                } else {
                    channelDiscountAmt = AmountUtil.addition(channelDiscountAmt, paymentOrderDetailBeanList.get(0).getMoneyOffSubsidyTotal());
                }
                if ("0".equals(paymentOrderDetailBeanList.get(0).getCouponMchntSettleMethod())) {
                    /*免充值需要减去商户卡券补贴金额*/
                    noRechargeAmt = AmountUtil.addition(noRechargeAmt, paymentOrderDetailBeanList.get(0).getCouponMchntSubsidy());
                    /*用户优惠金额累计*/
                    customerAmt = AmountUtil.addition(customerAmt, paymentOrderDetailBeanList.get(0).getCouponMchntSubsidy());
                } else {
                    channelDiscountAmt = AmountUtil.addition(channelDiscountAmt, paymentOrderDetailBeanList.get(0).getCouponTotalSubsidy());
                }
                rglog.debug("商户免充值金额:<{}>", noRechargeAmt);
                //对客营销金额=商户免充值营销金额
                mchntOrderInfo.setCustomerMarketAmt(customerAmt);
                //商户实际清算本金=原商户实际清算本金-对客营销金额
                mchntOrderInfo.setRealSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), noRechargeAmt));

                //商户手续费优惠金额
                String mchntFeeDiscount = mchntOrderInfo.getMchntDiscountFee();
                if (paymentOrderDetailBeanList.get(0).getMchntFeeDiscount() != null && AmountUtil.compare(paymentOrderDetailBeanList.get(0).getMchntFeeDiscount(), "0") == 1) {
                    mchntFeeDiscount = paymentOrderDetailBeanList.get(0).getMchntFeeDiscount();
                    feeDiscountFlag = AppParamConstant.YES;
                }

                //用户享受营销之后商户就不实时清算
                if (AppParamConstant.YES.equals(discountFlag)) {
                    rglog.info("当前用户享受营销,商户不支持实时清算");
                    mchntOrderInfo.setRealSettleFlag(OpmsParamConstant.OPMS_PARAM_NO);
                }

                //根据免充值金额对商户清算本金金额、商户结算金额、商户实收手续费、商户优惠手续费进行赋值
                if (AmountUtil.compare(noRechargeAmt, "0.00") == 1) {
                    /*实收商户手续费金额*/
                    String mchntFeeActual = mchntOrderInfo.getRealMchntFee();
                    if (paymentOrderDetailBeanList.get(0).getMchntFeeActual() != null) {
                        mchntFeeActual = paymentOrderDetailBeanList.get(0).getMchntFeeActual();
                    }
                    rglog.debug("商户免充值金额大于0,需要重新计算商户手续费....");

                    //重新计算商户手续费

                    /*计算商户手续费*/
                    CalcMchntFeeBean clearSrcObj = new CalcMchntFeeBean();
                    clearSrcObj.setMchntNo(mchntOrderInfo.getMchntNo());
                    clearSrcObj.setTransAmt(mchntOrderInfo.getRealSettleAmt());
                    clearSrcObj.setInstId(unionPayRequest.getHeader().getInstId());
                    clearSrcObj.setStageCode("");
                    clearSrcObj.setStageNum("");
                    clearSrcObj.setSubProdType(xmlTreeUtil.getXmlTreeStringValue("FEE_TYPE"));
                    clearSrcObj.setIgasBizProdType(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
                    CalcMchntFee clearMethod = new CalcMchntFee();
                    CalcMchntFeeResultBean calcMchntFeeResultBean = clearMethod.calcPayFee(clearSrcObj);
                    if (calcMchntFeeResultBean == null) {
                        rglog.error("使用免充值金额后重新计算商户手续费失败");
                        throw new BizException(RespCodeEnum.CALC_MCHNT_FEE_ERROR.getRespCode(), RespCodeEnum.CALC_MCHNT_FEE_ERROR.getRespDesc());
                    }

                    //更新商户订单数据
                    mchntOrderInfo.setFeeRate(calcMchntFeeResultBean.getFeeRate());
                    mchntOrderInfo.setFeeCappingAmt(calcMchntFeeResultBean.getFeeCappingAmt());
                    mchntOrderInfo.setFeeFixedAmt(calcMchntFeeResultBean.getFeeFixedAmt());
                    mchntOrderInfo.setMchntFee(calcMchntFeeResultBean.getMchntFee());
                    if (AmountUtil.compare(calcMchntFeeResultBean.getMchntFee(), mchntFeeActual) == 1) {
                        mchntOrderInfo.setRealMchntFee(mchntFeeActual);
                        mchntOrderInfo.setMchntDiscountFee(AmountUtil.subtraction(calcMchntFeeResultBean.getMchntFee(), mchntFeeActual));
                    } else {
                        mchntOrderInfo.setRealMchntFee(calcMchntFeeResultBean.getMchntFee());
                        mchntOrderInfo.setMchntDiscountFee("0.00");
                    }
                    String mchntSettleAmt = AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntOrderInfo.getRealMchntFee());
                    mchntOrderInfo.setMchntSettleAmt(mchntSettleAmt);
                    mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                } else {

                    rglog.debug("商户免充值金额小于等于0,使用营销调用结果计算商户手续费信息....");
                    /*实收商户手续费金额*/
                    String mchntFeeActual = mchntOrderInfo.getRealMchntFee();
                    if (paymentOrderDetailBeanList.get(0).getMchntFeeActual() != null) {
                        mchntFeeActual = paymentOrderDetailBeanList.get(0).getMchntFeeActual();
                    }

                    /*实时清算时，实收手续费四舍五入处理*/
                    if (AppParamConstant.YES.equals(mchntOrderInfo.getRealSettleFlag())) {
                        mchntFeeActual = AmountUtil.rounding(mchntFeeActual, 2);
                        if (mchntFeeDiscount == null || AmountUtil.compare(mchntFeeDiscount, "0") == 0) {
                            mchntFeeDiscount = "0.00";
                        } else {
                            mchntFeeDiscount = AmountUtil.subtraction(mchntOrderInfo.getMchntFee(), mchntFeeActual);
                        }
                    }
                    mchntOrderInfo.setMchntDiscountFee(mchntFeeDiscount);
                    mchntOrderInfo.setRealMchntFee(mchntFeeActual);
                    mchntOrderInfo.setMchntSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntFeeActual));
                    if (paymentOrderDetailBeanList.get(0).getCouponNo() != null) {
                        mchntOrderInfo.setRedeemCouponIds(paymentOrderDetailBeanList.get(0).getCouponNo());
                    }
                    mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                }
            }

            /*营销系统返回成功，更新订单支付订单状态为成功*/
            mompPayOrderInfo.setChannelDiscountAmt(mompResponse.getTotalSubsidy());
            mompPayOrderInfo.setSettleDate(DateUtil.getCurrentDate());
            mompPayOrderInfo.setRespDesc(mompResponse.getRespDesc());
            mompPayOrderInfo.setRespCode(mompResponse.getRespCode());
            mompPayOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            mompPayOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            mompPayOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, mompPayOrderInfo)) {
                rglog.warn("更新营销支付订单表失败:<{}>", JSON.toJSONString(mompPayOrderInfo));
            }
        }

        //是否使用优惠标识存入节点内
        if (AppParamConstant.NO.equals(discountFlag) && AppParamConstant.NO.equals(feeDiscountFlag)) {
            xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.NO);
        } else {
            xmlTreeUtil.setXmlTreeStringValue("discountFlag", AppParamConstant.YES);
        }
    }

    /**
     * 登记支付订单表
     *
     * @param userOrderInfo  用户订单表
     * @param channelCallCfg 通道服务调用配置表
     * @return 支付订单表
     * @throws Exception 异常
     */
    private PayOrderInfo registMompOrderInfo(UserOrderInfo userOrderInfo, ChannelCallCfg channelCallCfg) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        OrderService orderService = new OrderServiceImpl();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(userOrderInfo, payOrderInfo);
        payOrderInfo.setTxnNum(channelCallCfg.getTxnNum());
        payOrderInfo.setBizType(channelCallCfg.getBizType());
        payOrderInfo.setTxnDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        payOrderInfo.setTxnTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        payOrderInfo.setRealPayAmt(userOrderInfo.getOrderAmt());
        payOrderInfo.setPayType(PayTypeEnum.OTHER.getPayType());
        payOrderInfo.setPayerAcctType(AcctTypeEnum.COUPON.getAcctType());
        payOrderInfo.setPayeeAcctInfo("");
        payOrderInfo.setPayeeAcctType("");
        payOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
        payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
        payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
        payOrderInfo.setChannelSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        payOrderInfo.setChannelReconKey(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        payOrderInfo.setBizStatus(BizStatusEnum.INIT.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
            rglog.warn("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
            return null;
        } else {
            rglog.debug("登记支付订单表成功,payOrderInfo:<{}>", JSON.toJSONString(payOrderInfo));
        }
        return payOrderInfo;
    }

    /**
     * 登记支付订单表
     *
     * @param userOrderInfo 用户订单信息
     * @return 支付订单信息
     * @throws Exception 异常
     */
    private PayOrderInfo registPayOrderInfo(UserOrderInfo userOrderInfo, String prodType, String upacMchntNo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        OrderService orderService = new OrderServiceImpl();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(userOrderInfo, payOrderInfo);
        payOrderInfo.setTxnNum(userOrderInfo.getTxnNum());
        payOrderInfo.setTxnDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        payOrderInfo.setTxnTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        payOrderInfo.setRealPayAmt(userOrderInfo.getRealPayAmt());
        payOrderInfo.setPayType(PayTypeEnum.CUPS_CLOUD.getPayType());
        payOrderInfo.setPayerAcctType("");
        payOrderInfo.setSysSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setMsgDstId(ChannelEnum.UPAC.getChannelType());
        payOrderInfo.setDstChannelType(prodType);
        payOrderInfo.setDstCallIndex(OpmsParamConstant.STR_ZERO);
        payOrderInfo.setDstTxnNum("");
        payOrderInfo.setChannelSeqNum("");
        payOrderInfo.setChannelReconKey(upacMchntNo + xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM));
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
            rglog.warn("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
            return null;
        } else {
            rglog.debug("登记支付订单表成功,payOrderInfo:<{}>", JSON.toJSONString(payOrderInfo));
        }
        return payOrderInfo;
    }

    /**
     * 更新用户订单表/商户订单表 交易状态为拒绝，业务状态为失败
     *
     * @param userOrderInfo      用户订单
     * @param mchntOrderInfoList 商户订单
     * @param orderService       订单服务组件
     * @throws Exception 异常
     */
    private void updateUserAndMchntOrderInf(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo payOrderInfo, OrderService orderService) throws Exception {
        String currentDateTime = DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS");
        //更新用户订单表/商户订单表状态为失败
        userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
        userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
        userOrderInfo.setUpdateTime(currentDateTime);
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            mchntOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            mchntOrderInfo.setUpdateTime(currentDateTime);
        }
        boolean updateResCode = false;
        if (null == payOrderInfo) {
            updateResCode = orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, null);
        } else {
            payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            payOrderInfo.setUpdateTime(currentDateTime);
            updateResCode = orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo);
        }
        if (!updateResCode) {
            rglog.error("更新用户订单/商户订单信息失败");
        } else {
            rglog.debug("更新用户订单/商户订单信息成功");
        }
    }


    /**
     * 营销冲正
     *
     * @param channelCallCfg 通道服务调用配置
     * @throws Exception 异常
     */
    private void mompRevsal(ChannelCallCfg channelCallCfg) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        if (xmlTreeUtil.isExist("discountFlag") && AppParamConstant.YES.equals(xmlTreeUtil.getXmlTreeStringValue("discountFlag"))) {
            ComboPaymentRequest comboPaymentRequest = (ComboPaymentRequest) xmlTreeUtil.getXmlTreeObjectValue("comboPaymentRequest", ComboPaymentRequest.class);
            Header header = comboPaymentRequest.getHeader();
            ComboPaymentReversalRequest comboPaymentRevsalRequest = new ComboPaymentReversalRequest();
            header.setTxnNum(channelCallCfg.getCallChannelTxn());
            comboPaymentRevsalRequest.setOrigTraceNo(header.getTraceNo());
            header.setTraceNo(sysSeqNum + channelCallCfg.getCallIndex());
            comboPaymentRevsalRequest.setHeader(header);
            DubboService dubboService = new DubboServiceImpl();
            int iReturnCode = dubboService.asynCallDubboService(OpmsParamConstant.DUBBO_MOMP_PAYMENT_SERVICE, OpmsParamConstant.DUBBO_METHOD_MOMP_REVERSAL, comboPaymentRevsalRequest, "AsynComboPaymentRevsalService");
            if (iReturnCode != 0) {
                rglog.error("异步营销冲正服务注册失败！");
            }
        }
    }

    /**
     * 组应答报文
     *
     * @param instId        机构号
     * @param prodType      产品代码
     * @param upacMchntNo   全渠道商户号
     * @param orderId       订单号
     * @param orderTime     交易时间
     * @param orderAmt      订单金额
     * @param backNotifyUrl 后台通知地址
     * @return 响应信息
     * @throws Exception 异常
     */
    private BizResponse getResponse(String instId, String prodType, String upacMchntNo, String orderId, String orderTime, String orderAmt, String backNotifyUrl) throws Exception {

        //获取安全计划ID
        DstChannelCfgMapper dstChannelCfgMapper = new DstChannelCfgMapperImpl();
        DstChannelCfg dstChannelCfg = dstChannelCfgMapper.selectDstChannelCfgByPrimaryKey(instId, ChannelEnum.UPAC.getChannelType(), prodType);
        if (null == dstChannelCfg || StringUtil.isEmptyOrNull(dstChannelCfg.getSecPlanId())) {
            rglog.error("支付通道信息表未配置安全计划ID");
            throw new BizException(RespCodeEnum.SEC_PLAN_NOEXIT.getRespCode(), RespCodeEnum.SEC_PLAN_NOEXIT.getRespDesc());
        }

        //根据通道安全计划获取安全计划
        CertInfo certInfo = null;
        SecPlanInfoMapper secPlanInfoMapper = new SecPlanInfoMapperImpl();
        List<SecPlanInfo> secPlanInfoList = secPlanInfoMapper.selectSecPlanInfoBySecPlanId(instId, dstChannelCfg.getSecPlanId());
        if (null != secPlanInfoList && !secPlanInfoList.isEmpty()) {
            /* 加签证书 */
            Optional<SecPlanInfo> secPlanInfoOpt = secPlanInfoList.stream().filter(item -> item.getSecPlanType().equals(OpmsParamConstant.SIGN_CERT_TYPE)).findFirst();
            if (secPlanInfoOpt.isPresent()) {
                CertInfoMapper certInfoMapper = new CertInfoMapperImpl();
                certInfo = certInfoMapper.selectCertInfoByPrimaryKey(instId + secPlanInfoOpt.get().getSecPlanId() + secPlanInfoOpt.get().getSecPlanType());
            }
        }
        if (null == certInfo || AppParamConstant.NO.equals(certInfo.getKeyStatus())) {
            rglog.error("证书信息表中未配置全渠道加密证书或证书已失效");
            throw new BizException(RespCodeEnum.CERT_STATUS_INVALID.getRespCode(), RespCodeEnum.CERT_STATUS_INVALID.getRespDesc());
        }

        //通过证书获取私钥
        String privateKey;
        if (OpmsParamConstant.STR_TWO.equals(certInfo.getCertSaveType())) {
            rglog.info("证书以文件的方式存放，certSavePath:<{}>", certInfo.getCertSavePath());
            try {
                privateKey = FileUtils.readFileToString(new File(certInfo.getCertSavePath()));
            } catch (IOException e) {
                rglog.error("读取证书文件异常:{}", e.getMessage());
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
        } else {
            privateKey = certInfo.getCertValue();
        }

        //获取加签数据并加签
        Map<String, String> dataMap = genMessage(upacMchntNo, orderId, orderTime, orderAmt, certInfo.getCertId(), backNotifyUrl);
        boolean isSignSucc = OpmsUpacSecurityUtil.signBySecureKey(dataMap, privateKey, OpmsUpacSecurityUtil.UTF_8_ENCODING);
        if (!isSignSucc) {
            rglog.error("报文加签失败");
            throw new BizException(RespCodeEnum.GENERATE_SIGN_BLOCK_ERROR.getRespCode(), RespCodeEnum.GENERATE_SIGN_BLOCK_ERROR.getRespDesc());
        }
        String upacReqMsg = OpmsUpacSecurityUtil.getRequestParamString(dataMap, OpmsUpacSecurityUtil.UTF_8_ENCODING);

        UnionPayResponse unionPayResponseest = new UnionPayResponse();
        unionPayResponseest.setUpacOrderId(upacReqMsg);
        BizResponse<UnionPayResponse> bizResponse = new BizResponse<>();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(unionPayResponseest);
        return bizResponse;
    }

    /**
     * 生成网关支付请求报文
     *
     * @param upcMchntNo    全渠道商户号
     * @param orderId       订单号
     * @param txnTime       交易时间
     * @param orderAmt      订单金额
     * @param certId        证书ID
     * @param backNotifyUrl 后台通知地址
     * @return 交易报文信息
     */
    private Map<String, String> genMessage(String upcMchntNo, String orderId, String txnTime, String orderAmt, String certId, String backNotifyUrl) {

        HashMap<String, String> data = new HashMap<>();
        //版本号
        data.put("version", OpmsUpacSecurityUtil.VERSION_5_1_0);
        //字符集编码 可以使用UTF-8,GBK两种方式
        data.put("encoding", OpmsUpacSecurityUtil.UTF_8_ENCODING);
        //产品类型
        data.put("bizType", "000201");
        //订单发送时间，每次发交易测试需修改为被查询的交易的订单发送时间
        data.put("txnTime", txnTime);
        //后台通知地址
        data.put("backUrl", backNotifyUrl);
        //交易币种
        data.put("currencyCode", "156");
        //交易金额
        data.put("txnAmt", orderAmt);
        //交易类型 00-默认
        data.put("txnType", "01");
        //交易子类型  默认01:自助消费
        data.put("txnSubType", "01");
        //接入类型 默认为 0:商户接入
        data.put("accessType", "0");
        //签名
        data.put("signature", "");
        //签名方法
        data.put("signMethod", OpmsUpacSecurityUtil.SIGNMETHOD_RSA);
        //渠道类型 B2C网关支付，手机wap支付
        data.put("channelType", ChannelTypeEnum.MAPP.getDstType());
        //商户代码
        data.put("merId", upcMchntNo);
        //接入类型，商户接入固定填0，不需修改
        data.put("accessType", "0");
        //商户订单号
        data.put("orderId", orderId);
        //证书ID
        data.put("certId", certId);

        return data;
    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        Optional<ChannelCallCfg> channelCallCfgOpt = channelCallCfgList.stream().filter(item ->
                item.getBizScene().equals(ShareParamConstant.CALL_CFG_DEFAULT_BIZ_SCENE)).findFirst();
        return channelCallCfgOpt.orElse(null);
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        return CheckResultEnum.PASSED;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        return transStatusEnum;
    }
}
